// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "MemoryScan.h"
#include <Psapi.h>
#pragma comment(lib, "psapi.lib")

// 这里是第一种方法获取engfun地址
void * GetEngineFuncs(void)
{
	PCHAR String = "ScreenFade";
	DWORD Address = FindMemoryClone(g_nHwBase, g_nHwBase + g_nHwSize, String, strlen(String));
	return (void*)*(DWORD*)(FindReference(g_nHwBase, g_nHwBase + g_nHwSize, Address) + 0x0D);
}

// 计算地址
void AutoOffsets() 
{ 
	static bool NotPatched = true; 
	if (NotPatched) 
	{
		// 这里是第二种方法获取engfun地址
		int a; 
		for(a=0x01D00000;a<0x01D0FFFF;a++) 
		{ 
			if(*(PBYTE)(a) == 0x68 && *(PBYTE)(a + 0x05) == 0xE8 && 
				*(PBYTE)(a + 0x0A) == 0x6A && *(PBYTE)(a + 0x0B) == 0x07 && 
				*(PBYTE)(a + 0x0C) == 0x68 && *(PBYTE)(a + 0x11) == 0xFF && 
				*(PBYTE)(a + 0x12) == 0x15 && *(PBYTE)(a + 0x17) == 0x68) 
			{ 
				pEngfuncs = (cl_enginefunc_t*)*(DWORD*)(a+0x0D); 
			} 
		}

		if(pEngfuncs == NULL)
		{
			pEngfuncs = (cl_enginefunc_t *)GetEngineFuncs();
			if(pEngfuncs == NULL)
			{
				MessageBox(NULL, "not found.", NULL, NULL);
				return;
			}
		}

#if 0
		int c; 
		for(c=0x01D00000;c<0x01D0FFFF;c++) 
		{ 
			if(*(PBYTE)(c) == 0x68 && *(PBYTE)(c + 0x05) == 0x68 && 
				*(PBYTE)(c + 0x0A) == 0x6A && *(PBYTE)(c + 0x0B) == 0x01 && 
				*(PBYTE)(c + 0x0C) == 0xFF && *(PBYTE)(c + 0x0D) == 0xD0 && 
				*(PBYTE)(c + 0x0E) == 0x83 && *(PBYTE)(c + 0x27) == 0xC3) 
			{ 
				pStudio/*pIEngineStudio*/ = (engine_studio_api_s*)*(DWORD*)(c+0x01); 
			} 
		} 
		int d; 
		for(d=0x01D60000;d<0x01D6FFFF;d++) 
		{ 
			if(*(PBYTE)(d) == 0x68 && *(PBYTE)(d + 0x05) == 0xFF && 
				*(PBYTE)(d + 0x06) == 0x15 && *(PBYTE)(d + 0x0B) == 0x68 && 
				*(PBYTE)(d + 0x10) == 0xFF && *(PBYTE)(d + 0x11) == 0x15 && 
				*(PBYTE)(d + 0x16) == 0xA1 && *(PBYTE)(d + 0x1B) == 0x83) 
			{ 
				slots = (DWORD*)(*(DWORD*)(d+0x01)); 
				tempslots = (DWORD)slots;
			} 
		} 

		if( ((DWORD*)pEngfuncs <= (DWORD*)(0x01EB52B8)) )//RetartPtr
		{
			RetartPtr = (DWORD*)0x01A179D0;
		}
		else
		{
			RetartPtr = (DWORD*)0x01A179F0;
		}
#endif

		NotPatched = false; 
	} 
}

DWORD GetPEImageSize(HMODULE hModule)
{
	try
	{
		if((DWORD)hModule == NULL)
			return 0;

		DWORD	nPID	 = GetCurrentProcessId();
		HANDLE	hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_QUERY_LIMITED_INFORMATION, FALSE, nPID);
		if(hProcess == INVALID_HANDLE_VALUE)
			return FALSE;

		MODULEINFO	infoMod;
		DWORD		infoSize;
		infoSize = sizeof(MODULEINFO);
		ZeroMemory(&infoMod,infoSize);

		if(GetModuleInformation(hProcess,hModule,&infoMod,infoSize))
		{
			CloseHandle(hProcess);
			return infoMod.SizeOfImage;
		}
		else
		{
			char szMsg[MAX_PATH];
			wsprintf(szMsg,"GetModuleInformation failed : %d  %08x",GetLastError(),(DWORD)hModule);
			OutputDebugString(szMsg);
		}

		PBYTE				pInfo = NULL;
		PIMAGE_DOS_HEADER	pImgDos = NULL;
		PIMAGE_NT_HEADERS	pImgNt = NULL;

		CloseHandle(hProcess);
		pInfo   = (PBYTE)hModule;
		if(pInfo == NULL)
			return 0;

		pImgDos = (PIMAGE_DOS_HEADER)pInfo;
		if(pImgDos == NULL)
			return 0;

		if(pImgDos->e_magic==IMAGE_DOS_SIGNATURE)
		{
			pImgNt = (PIMAGE_NT_HEADERS)&pInfo[pImgDos->e_lfanew];
			if(pImgNt)
			{
				if(pImgNt->Signature==IMAGE_NT_SIGNATURE)
				{
					return pImgNt->OptionalHeader.SizeOfImage;
				}
			}
		}

		return 0;
	}
	catch (...)
	{
	}
	return 0;
}


void *MH_SearchPattern(void *pStartSearch, DWORD dwSearchLen, char *pPattern, DWORD dwPatternLen)
{
	DWORD dwStartAddr = (DWORD)pStartSearch;
	DWORD dwEndAddr = dwStartAddr + dwSearchLen - dwPatternLen;

	while (dwStartAddr < dwEndAddr)
	{
		bool found = true;

		for (DWORD i = 0; i < dwPatternLen; i++)
		{
			char code = *(char *)(dwStartAddr + i);

			if (pPattern[i] != 0x2A && pPattern[i] != code)
			{
				found = false;
				break;
			}
		}

		if (found)
			return (void *)dwStartAddr;

		dwStartAddr++;
	}

	return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		StartInitApi();
		break;

	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
		break;
        
	case DLL_PROCESS_DETACH:
		CloseNetwork();
		break;
	}
	return TRUE;
}

